#include "Col.ph"
#ifdef __GNUG__
#pragma implementation
#endif

#include "RLEFilter.h"
#include "ET_stdio.h"

//---- RLEEncoder --------------------------------------------------------------

RLEEncoder::RLEEncoder() : RLEFilter()
{
	rep= 0;
}

void RLEEncoder::Flush()
{
	if (count > 0) {
		if (rep > 1) {
			sb->sputc(257-count);
			sb->sputc(buf[0]);
		} else {
			sb->sputc(count-1);
			sb->sputn((char*)buf, count);
		}
		count= rep= 0;
	}
}

void RLEEncoder::Close()
{
	Flush();
	sb->sputc(128);
}

int RLEEncoder::Overflow(u_char *bp, int n)
{
	register u_char *p= bp;
	while (n-- > 0) {
		u_char c= *p++;
		if (count > 0) {
			if (c == buf[count-1]) {        // continue or start run
				if (count > rep+1) {
					sb->sputc(count-2);
					sb->sputn((char*)buf, count-1);
					count= rep= 0;
					buf[count++]= c;
				}
				rep++;
			} else {                // differ
				if (rep >= 1) {
					sb->sputc(257-count);
					sb->sputc(buf[0]);
					count= 0;
				}
				rep= 0;
			}
		}
		buf[count++]= c;
		if (count >= 128)
			Flush();
	}
	return p-bp;
}

//---- RLEDecoder --------------------------------------------------------------

RLEDecoder::RLEDecoder(bool compatible) : RLEFilter()
{
	repeat= FALSE;
	compat= compatible;
}

int RLEDecoder::Underflow(u_char *bp, int n)
{
	register u_char *p= bp;
	register int i;

	if (count == EOF)
		return EOF;

	for (i= 0; i < n; i++) {
		if (count == 0) {
			count= sb->sgetc();
			if (count == EOF)
				break;
			sb->stossc();
			if (compat) {
				if (count >= 128) {
					count-= 127;
					repeat= FALSE;
				} else {
					count++;
					value= sb->sgetc();
					sb->stossc();
					repeat= TRUE;
				}
			} else {
				if (count > 128) {
					count= 257-count;
					value= sb->sgetc();
					sb->stossc();
					repeat= TRUE;
				} else if (count < 128) {
					count++;
					repeat= FALSE;
				} else if (count == 128) {
					count= EOF;
					break;
				}
			}
		}
		if (repeat)
			*p++= value;
		else {
			*p++= sb->sgetc();
			sb->stossc();
		}
		count--;
	}
	return p-bp;
}

